package com.lgl.scsheader.sameCityChart.service;

import com.lgl.scsapi.base.dao.DaoSupport;
import com.lgl.scsapi.system.model.PageData;
import com.lgl.scsapi.system.model.SysUser;
import com.lgl.scsapi.util.utils.Constants;
import com.lgl.scsapi.util.utils.Tools;
import org.springframework.data.redis.connection.RedisCommands;
import org.springframework.data.redis.core.RedisCallback;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.List;

/**
 * 用户信息统计图表service
 */

@Service("userInfoChartService")
public class UserInfoChartService {
	@Resource(name = "daoSupport")
	private DaoSupport dao;
	@Resource
	private RedisTemplate redisTemplate;

	/**
	 * 获取每个月用户注册数
	 * @param registerPd 统计参数，如统计的某年年份
	 * @return 每个月用户注册数
	 */
	public List<PageData> listMonthUserRegisterNum(PageData registerPd){
		int thisYear = Tools.getYear(registerPd);
		Tools.initDate(registerPd,thisYear,thisYear);
		return (List<PageData>) dao.findForList("AppUserMapper.listMonthUserRegisterNum", registerPd);
	}

    /**
     * 获取某年所有月份的登录用户数
	 * @param sysUser 登录用户
     * @param userNumPd 统计参数
     * @return 所有月份的登录用户数
     */
    public List<PageData> listYearLoginUserNum(SysUser sysUser, PageData userNumPd){
        int thisYear = Tools.getYear(userNumPd);
		userNumPd.put("thisYear",thisYear);
		List<PageData> userNumList = (List<PageData>) dao.findForList("AppUserMapper.listLoginOfUserNum", userNumPd);
		Calendar calendar = Calendar.getInstance();
		int day = calendar.get(Calendar.DAY_OF_MONTH), month = calendar.get(Calendar.MONTH) + 1;
		String tempSaveKey = Constants.USER_LOGIN_SET_PRE + sysUser.getUserName();
		byte[][] keyBytes = new byte[day][];
		for (int m = 1; m <= day; m ++){
			keyBytes[m - 1] = (Constants.USER_LOGIN_SET_PRE + month + m).getBytes();
		}
		redisTemplate.execute((RedisCallback) con ->
				con.bitOp(RedisCommands.BitOperation.OR,tempSaveKey.getBytes(),keyBytes));
		long loginUserNum = (Long) redisTemplate.execute((RedisCallback) con -> con.bitCount(tempSaveKey.getBytes()));
		redisTemplate.delete(tempSaveKey);
		for(PageData pageData : userNumList){
			if (pageData.containsKey(month)){
				pageData.put(month,loginUserNum);
				break;
			}
		}
		return userNumList;
    }

    /**
     * 获取某个月的用户登录数
     * @param userNumPd 参数，某个月的参数
     * @return 某个月的用户登录数
     */
    public List<PageData> listMonthLoginUserNum(SysUser sysUser,PageData userNumPd){
        List<PageData> userNumList = new ArrayList<>(20);
        int month = Integer.parseInt(userNumPd.getString("thisMonth")),
                year = Integer.parseInt(userNumPd.getString("thisYear"));
        Calendar calendar = Calendar.getInstance();
        int currentMonth = calendar.get(Calendar.MONTH) + 1,
                currentDay = calendar.get(Calendar.DAY_OF_MONTH);
        calendar.set(Calendar.YEAR,year);
        calendar.set(Calendar.MONTH,month - 1);
        int maxDay = calendar.getActualMaximum(Calendar.DAY_OF_MONTH);
        //如果查询的不是当前月，则从1号到最后一天都统计，如果是当前月，则只统计到当天
        currentDay = currentMonth == month ? currentDay : maxDay;
        String tempSaveKey = Constants.USER_LOGIN_SET_PRE + sysUser.getUserName();
        PageData resultPd;
        for (int m = 1; m <= currentDay; m ++){
            String key = Constants.USER_LOGIN_SET_PRE + month + m;
            redisTemplate.execute((RedisCallback) con ->
                    con.bitOp(RedisCommands.BitOperation.OR,tempSaveKey.getBytes(),key.getBytes()));
            long loginUserNum = (Long) redisTemplate.execute((RedisCallback) con -> con.bitCount(tempSaveKey.getBytes()));
            resultPd = new PageData(4);
            resultPd.put("mo",m);
            resultPd.put("loginUserNum",loginUserNum);
            userNumList.add(resultPd);
        }
        redisTemplate.delete(tempSaveKey);
        //如果不是当前月，且当天不是月份的最后一天
        if (month == currentMonth && currentDay < maxDay) {
            for (int d = currentDay; d <= maxDay; d++) {
                resultPd = new PageData(4);
                resultPd.put("mo", d);
                resultPd.put("loginUserNum", 0);
                userNumList.add(resultPd);
            }
        }
        return userNumList;
    }

    /**
     * 获取平台上所有用户各年龄的数量及占比
     * @return 所有用户各年龄的数量及占比数据集
     */
    public List<PageData> listAllUserAgeSection(){
        return (List<PageData>) dao.findForList("AppUserMapper.listAllUserAgeSection", null);
    }
    /**
     * 获取各等级的用户数量及占比
     * @return 各等级的用户数量及占比数据集
     */
    public List<PageData> listLevelUserNum(){
        return (List<PageData>) dao.findForList("AppUserMapper.listLevelUserNum", null);
    }
    /**
     * 获取用户男女的数量
     * @return 男女的数量数据集
     */
    public List<PageData> listSexUserNum(){
        return (List<PageData>) dao.findForList("AppUserMapper.listSexUserNum", null);
    }
    /**
     * 获取热门城市用户的数量
     * @return 热门城市用户的数量数据集
     */
    public List<PageData> listHotCityUserNum(){
        PageData hotCityPd = new PageData(3);
        hotCityPd.put("hotCityArr",Constants.HOT_CITY_IDS);
        return (List<PageData>) dao.findForList("AppUserMapper.listHotCityUserNum", hotCityPd);
    }
    /**
     * 获取手机/微信等用户类型的数量
     * @return 手机/微信等用户类型的数据集
     */
    public List<PageData> listClientUserNum(){
        return (List<PageData>) dao.findForList("AppUserMapper.listClientUserNum", null);
    }

}